#include "CNet.h"

// 服务器启动函数
void Server_Start(void* self) {
    Server* s = (Server*)self;
    printf(" 创建socket at IP: %s, Port %d\n", s->IP, s->Port);

    
    // ipv4地址
    struct sockaddr_in server_addr;
    int opt = 1;
    
    // 创建套接字
    s->listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s->listen_fd == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    
    // 设置套接字选项
    /*
        25/4/8 我并不能理解下面这些抄来的乱七八糟的东西是什么，但是冷静下来觉得并不需要理解，我知道大概做了个什么事情，就足够了。以后有时间再来解决
    */
    if (setsockopt(s->listen_fd, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt))) {
        perror("setsockopt");
        close(s->listen_fd);
        exit(EXIT_FAILURE);
    }
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(s->IP);
    server_addr.sin_port = htons(s->Port);
    
    // 绑定套接字和服务器地址
    if (bind(s->listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind failed");
        close(s->listen_fd);
        exit(EXIT_FAILURE);
    }
    
    // 开始监听
    if (listen(s->listen_fd, 10) < 0) {
        perror("listen");
        close(s->listen_fd);
        exit(EXIT_FAILURE);
    }
    
    printf("服务器 %s 创建成功, 开始进行监听,等待客户端连接...\n", s->Name);
    int connectId=0;
    // 接受客户端连接
    while (1) {
        int client_fd;
        struct sockaddr_in client_addr;
        int addrlen = sizeof(client_addr);
        
        // 阻塞，一直阻塞到accept成功或者失败
        if ((client_fd = accept(s->listen_fd, (struct sockaddr *)&client_addr, (socklen_t*)&addrlen)) < 0) {
            perror("accept失败,直接进入下一个循环,此次连接作废");
            continue;
        }
        printf("New connection from %s:%d\n", 
               inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        
        
        // 创建线程处理客户端连接，开启一个线程进行处理
        int* pclient_fd = malloc(sizeof(int));
        *pclient_fd = client_fd;
        
        IConnect* connection=NewConnection(pclient_fd,connectId,s->router);
        printf("NewConnection之后,转换为IConnect的地址 %p\n",connection);
        connectId++;
        connection->Start(connection);
        connection->Stop(connection);
    }
}



// 服务器停止函数
void Server_Stop(void* self) {
    Server* s = (Server*)self;
    printf("[STOP] Zinx server, name %s\n", s->Name);
    
    if (s->listen_fd > 0) {
        close(s->listen_fd);
        s->listen_fd = -1;
    }
    
    // TODO: 清理其他资源
}

// 创建一个新的线程来运行服务
void Server_Serve(void* self) {
    Server* s = (Server*)self;

    pthread_t server_thread;
    if (pthread_create(&server_thread, NULL, Server_Start, s) < 0) {
        perror("could not create thread");
        exit(EXIT_FAILURE);
    }
    pthread_detach(server_thread);
        
}

// 创建新服务器实例,注意这里生成的是一个接口
IServer* NewServer(const char* name) {
    //堆区内存分配
    Server* s = (Server*)malloc(sizeof(Server));
    
    // 手动初始化接口
    s->vtable.Start = Server_Start;
    s->vtable.Stop = Server_Stop;
    s->vtable.Serve = Server_Serve;
    s->vtable.AddRouter=Server_AddRouter;
    // 初始化服务器属性
    strncpy(s->Name, name, sizeof(s->Name)-1);
    s->Name[sizeof(s->Name) - 1] = '\0';// 这里差点忘记手动添加\0
    strncpy(s->IPVersion, "tcp4", sizeof(s->IPVersion)-1);
    strncpy(s->IP, "0.0.0.0", sizeof(s->IP)-1);// 这里监听的是0.0.0.0，即监听来自所有ip地址的连接
    s->Port = 7777;
    s->listen_fd = -1;
    s->router=0;
    IRouter* router= NewRouter();
    s->vtable.AddRouter(s,router);
    return (IServer*)s;
}
void Server_AddRouter(void* self, IRouter* router){
    Server* s = (Server*)self;
    s->router=router;
}